package com.small.site.service.impl;

import com.google.common.collect.Lists;
import com.small.site.base.IPermissionService;
import com.small.site.base.IRolePermissionService;
import com.small.site.enums.ResponseCode;
import com.small.site.exception.BusinessException;
import com.small.site.pojo.SysPermission;
import com.small.site.pojo.SysRolePermission;
import com.small.site.service.PermissionService;
import com.small.site.util.Builder;
import com.small.site.util.IdWorker;
import com.small.site.util.R;
import com.small.site.vo.PermissionVo;
import com.small.site.vo.req.PermissionRespNodeTreeVo;
import com.small.site.vo.resp.PermissionRespNodeVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author xiaochi
 * @date 2021/12/14 15:12
 * @desc PermissionServiceImpl
 */
@Slf4j
@Service
@SuppressWarnings("all")
public class PermissionServiceImpl implements PermissionService {

    @DubboReference(check = false)
    private IPermissionService permissionService;
    @DubboReference(check = false)
    private IRolePermissionService rolePermissionService;
    @Autowired
    private IdWorker idWorker;

    /**
     * 获取所有权限（包括按钮），角色添加/编辑/分配权限时用到的结结构数据
     * @return
     */
    @Override
    public List<PermissionRespNodeVo> selectAllTree() {
        return getTree(permissionService.findByWhere(SysPermission.builder().deleted(1).build()),false);
    }

    /**
     * 查询所有权限列表（树形表格结果数据展示），表格列表时展示
     * 树形表格结果数据组装
     * @return
     */
    @Override
    public List<PermissionVo> selectAll() {
        List<SysPermission> sysPermissionList = permissionService.findByWhere(SysPermission.builder().deleted(1).build());
        List<PermissionVo> list = Lists.newArrayList();
        if (!sysPermissionList.isEmpty()){
            for (SysPermission sysPermission : sysPermissionList) {
                PermissionVo permissionVo = new PermissionVo();
                BeanUtils.copyProperties(sysPermission,permissionVo);
                for (SysPermission permission : sysPermissionList) {
                    if(StringUtils.isNotBlank(sysPermission.getPid()) && StringUtils.isNotBlank(permission.getId()) && StringUtils.equals(sysPermission.getPid(),permission.getId())){
                        permissionVo.setPidName(permission.getName());
                        break;
                    }
                }
                list.add(permissionVo);
            }
        }
        return list;
    }

    /**
     * 根据用户id查询用户拥有的权限列表，不包括菜单结构，用于 security认证授权
     * @return
     */
    @Override
    public List<SysPermission> permissionListByUserId(String userId) {
        List<SysPermission> permissionList = permissionService.getPermissionByUserId(userId);
        return permissionList;
    }

    /**
     * 筛选用户拥有的权限列表，包括菜单结构，用于返回用户菜单
     * @param permissionList
     * @return
     */
    @Override
    public List<PermissionRespNodeVo> permissionTreeListMenu(List<SysPermission> permissionList) {
        return getTree(permissionList,true);
    }

    //==================== start 递归筛选 目录与菜单权限（用于角色列表-添加/编辑/分配权限时选择树结构，登录权限查询用到） ====================
    /** 目录1；菜单2；按钮3
     * type=true 递归遍历到菜单
     * type=false 递归遍历到按钮
     * @param permissionList 用户拥有的权限列表数据
     * @param isOnlyMenuType 是否遍历到菜单，不包括按钮
     * @return
     */
    private List<PermissionRespNodeVo> getTree(List<SysPermission> permissionList,boolean isOnlyMenuType){
        // 无父级 pid 默认 0
        return _getTree(permissionList,"0",isOnlyMenuType);
    }
    private List<PermissionRespNodeVo> _getTree(List<SysPermission> permissionList,String pid,boolean type){
        List<PermissionRespNodeVo> list = Lists.newArrayList();
        if (null == permissionList || permissionList.isEmpty()){
            return list;
        }
        for (SysPermission permission : permissionList){
            if (pid.equals(permission.getPid())){
                // 遍历到按钮 与 不遍历到按钮 都会执行
                if (!type || (type && permission.getType().intValue() != 3)){
                    PermissionRespNodeVo respNodeVo = new PermissionRespNodeVo();
                    respNodeVo.setId(permission.getId());
                    respNodeVo.setTitle(permission.getTitle());
                    respNodeVo.setIcon(permission.getIcon());
                    respNodeVo.setPath(permission.getUrl());
                    respNodeVo.setName(permission.getName());
                    respNodeVo.setChildren(_getTree(permissionList,permission.getId(),type));
                    list.add(respNodeVo);
                }
            }
        }
        return list;
    }
    //==================== end 递归筛选 目录与菜单权限（用于角色列表-添加/编辑/分配权限时选择树结构，登录权限查询用到） ====================

    //------------------------------------------------ 权限列表 start -----------------------------------------------

    /**
     * 新增权限
     * @param permissionReqVo
     * @return
     */
    @Override
    public R<String> addPermission(SysPermission sysPermission) {
        sysPermission.setId(String.valueOf(idWorker.nextId()));
        int result = permissionService.insert(sysPermission);
        if (result == 0){
            return R.error();
        }
        return R.ok();
    }

    /**
     * 编辑权限
     * @param buildEntity
     * @return
     */
    @Override
    public R<String> updatePermission(SysPermission sysPermission) {
        // 1.验证表单数据
        verifyForm(sysPermission);
        SysPermission permission = permissionService.findOne(sysPermission.getId());
        if (sysPermission == null){
            log.error("传入的id在数据库中不存在,{}",sysPermission);
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        // 2.验证 所属菜单是否发生了变化
        if (!permission.getPid().equals(permission.getPid())){
            // 目录 菜单 按钮，如 菜单有子级按钮，则不能吧当前菜单更新为按钮类型
            // 所属菜单发生了变化要校验该权限是否存在子集
            int count = permissionService.selectChild(sysPermission.getId());// 通过 id 查询是否有子级
            if (count > 0){
                return R.error(ResponseCode.OPERATION_MENU_PERMISSION_UPDATE.getMessage());
            }
        }
        // 3.更新菜单信息
        int result = permissionService.updateById(sysPermission);
        if (result == 0){
            return R.error();
        }
        return R.ok();
    }

    /** 删除权限
     * @param permissionId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<String> deletedPermission(String permissionId) {
        //判断是否有子集关联，有则不能删除
        int result = permissionService.selectChild(permissionId);
        if (result > 0){
            throw new BusinessException(ResponseCode.ROLE_PERMISSION_RELATION);
        }
        //通过权限id删除相关角色和该菜单权限的关联表信息
        rolePermissionService.deleteByWhere(SysRolePermission.builder().permissionId(permissionId).build());
        result = permissionService.updateById(SysPermission.builder().id(permissionId).deleted(0).build());
        if (result == 0){
            throw new BusinessException(ResponseCode.ERROR);
        }
        return R.ok();
    }

    /**
     * 添加权限的上级选择权限树结构展示（递归），不需要展示到按钮
     * @return
     */
    @Override
    public List<PermissionRespNodeTreeVo> selectAllMenuByTree() {
        // 设置一个最顶级的吗，默认选项
        List<SysPermission> sysPermissionList = permissionService.findAll();

        List<PermissionRespNodeTreeVo> list = Lists.newArrayList();
        list.add(Builder.of(PermissionRespNodeTreeVo::new)
                .with(PermissionRespNodeTreeVo::setId,"0")
                .with(PermissionRespNodeTreeVo::setTitle,"顶级菜单")
                .with(PermissionRespNodeTreeVo::setLevel,1)
                .build());
        list.addAll(setPermissionLevelTree(sysPermissionList,"0",1));
        return list;
    }
    // 递归设置级别，用于权限列表 添加/编辑 所属菜单树结构数据
    private List<PermissionRespNodeTreeVo> setPermissionLevelTree(List<SysPermission> permissionsList,String parentId,int level){
        List<PermissionRespNodeTreeVo> list = Lists.newArrayList();
        for (SysPermission sysPermission : permissionsList) {
            if (sysPermission.getType().intValue() != 3 && sysPermission.getPid().equals(parentId)){
                list.add(Builder.of(PermissionRespNodeTreeVo::new)
                        .with(PermissionRespNodeTreeVo::setId,sysPermission.getId())
                        .with(PermissionRespNodeTreeVo::setTitle,sysPermission.getTitle())
                        .with(PermissionRespNodeTreeVo::setLevel,level)
                        .build());
                list.addAll(setPermissionLevelTree(permissionsList,sysPermission.getId(),level+1));
            }
        }
        return list;
    }

    // 权限添加 / 编辑 验证参数
    private void verifyForm(SysPermission sysPermission){
        // 默认顶级 无父级 pid 默认 0
        //操作后的菜单类型是目录的时候 父级必须为目录
        //操作后的菜单类型是菜单的时候，父类必须为目录类型
        //操作后的菜单类型是按钮的时候 父类必须为菜单类型
        Integer type = sysPermission.getType();
        String pid = sysPermission.getPid();
        if (null != type && StringUtils.isNotBlank(pid)){
            SysPermission permission = permissionService.findOne(pid);
            if (type == 1){
                if (permission != null && permission.getType() > 1){// 父级 只能为 无父级/目录类型  0 / 1
                    throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_CATALOG_ERROR);
                }
            }else if (type == 2) {// 父级 只能为目录类型 1
                if ("0".equals(pid) || (permission != null && permission.getType() != 1)){// 父级 只能为目录类型 1
                    throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_MENU_ERROR);
                }
                if (StringUtils.isBlank(sysPermission.getUrl())){
                    throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_URL_NOT_NULL);
                }
            }else if (type == 3) {// 父级 只能为菜单类型 2
                if ("0".equals(pid) || (permission != null && permission.getType() != 2)){
                    throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_BTN_ERROR);
                }
                if(StringUtils.isEmpty(sysPermission.getPerms())){
                    throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_URL_PERMS_NULL);
                }
                if(StringUtils.isEmpty(sysPermission.getUrl())){
                    throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_URL_NOT_NULL);
                }
                if(StringUtils.isEmpty(sysPermission.getMethod())){
                    throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_URL_METHOD_NULL);
                }
                if(StringUtils.isEmpty(sysPermission.getCode())){
                    throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_URL_CODE_NULL);
                }
            }
        }else{
            throw new BusinessException(ResponseCode.DATA_ERROR);
        }
    }
    //------------------------------------------------ 权限列表 end -----------------------------------------------

}
